#include <stdio.h>


#include <string.h>
#include <stdlib.h>
#include <errno.h>


// int main()
// {
//     int arr[10] = { 0 };
//     int* p = (int*)malloc(0X40);
//     if(p == NULL)//这部分也可改为用assert来判断
//     {
//         printf("%s\n",strerror(errno));
//         return 1;//正常返回返回0，错误返回返回1
//     }
//     int i = 0;
//     for(i = 0;i < 10;i++)
//     {
//         *(p + i) = i;
//     }
//     for(i = 0;i < 10;i++)
//     {
//         printf("%d ",*(p + i));
//     }
//     free(p);//free (p)只会释放空间，但p作为指针变量不会变化
//     p = NULL;
//     //当不写free时  不代表内存空间就不回收了
//     //当程序退出时，系统会自动回收内存空间
//     //内存泄漏 申请内存后没有使用 但又一直不归还，其他程序
//     //一直无法用这部分空间 就是内存泄漏
//     return 0;
// }



// int main()
// {
//     int arr[10] = { 0 };
//     int* p = (int*)malloc(40);
//     if(p == NULL)
//     {
//         printf("%s\n",strerror(errno));
//         return 1;
//     }
//     int i = 0;
//     for(i = 0;i < 10;i++)
//     {
//         *(p + i) = i;
//     }
//     for(i = 0;i < 10;i++)
//     {
//         printf("%d ",*(p + i));
//     }
//     int* ptr = (int*)realloc(p,80);//不直接用p接收是因为有分配失败的可能
//     if(ptr != NULL)
//     {
//         p = ptr;
//     }
//     for(i = 0;i < 10;i++)
//     {
//         printf("%d ",*(p + i));
//     }
//     free(p);
//     p = NULL;
//     return 0;
// }


// //动态内存常见错误之一 
// //使用free释放动态开辟内存的一部分而非全部
// int main()
// {
//     int* p = (int*) malloc (40);
//     if(p == NULL)
//     {
//         return 1;
//     }
//     int i = 0;
//     for(i = 0;i < 10;i++)
//     {
//         *p = i;
//         p++;//不建议这种写法
//     }
//     free(p);//for循环内代码已经改变了p指向位置
//     p = NULL;
//     return 0;
// }



//几道动态内存经典试题

// //1
// void GetMemory(char *p)
// {
//     p = (char *)malloc(100);//形参的改动无法改变实参
//     //出函数 p销毁，无法再找到动态开辟内存空间了 内存泄漏
// }
// void Test(void)
// {
//     char *str = NULL;
//     GetMemory(str);//应该用&str来传参，同时函数接收参数格式为char** 
//     strcpy(str, "hello world");//str是空指针 解引用是会崩溃
//     printf(str);
// }
// int main()
// {
//     Test();
//     return 0;
// }

// int main()
// {
//     printf("hello world\n");//相当于传递的传输为字符串的首地址 即h的地址
//     char* p = "hello world";
//     printf(p);//与上上行等价
//     return 0;
// }


// //2
// char *GetMemory(void)
// {
//     char p[] = "hello world";//函数内部创建的临时数组 函数返回时就不存在了
//     return p;
// }
// void Test(void)
// {
//     char *str = NULL;
//     str = GetMemory();//str就是野指针
//     printf(str);
// }
// int main()
// {
//     Test();
//     return 0;
// }



// //3
// void GetMemory(char **p, int num)
// {
//     *p = (char *)malloc(num);
// }
// void Test(void)
// {
//     char *str = NULL;
//     GetMemory(&str, 100);
//     strcpy(str, "hello");
//     printf(str);//问题是没有free
// }
// int main()
// {
//     Test();
//     return 0;
// }



// //4
// void Test(void)
// {
//     char *str = (char *)malloc(100);
//     strcpy(str, "hello");
//     free(str);//str变成野指针
//     if (str != NULL)
//     {
//         strcpy(str, "world");
//         printf(str);
//     }
// }
// int main()
// {
//     Test();
//     return 0;
// }


//作业 
//BC115 最大公约数和最小公倍数之和

// //遍历法 以18 24为例
// //最大公约数<=18 则从18开始递减检查24与18能否都整除该数
// //最小公倍数>=24 则检查24的整数倍 能否整除18
// int main()
// {
//     int n = 0;
//     int m = 0;
//     while(scanf("%d %d",&n,&m) == 2)
//     {
//         int max = n > m ? n:m;
//         int min = n < m ? n:m;
//         int b = 0;
//         int y = 0;
//         int i = min;
//         while(1)
//         {
//             if(m % i == 0 && n % i ==0)
//             {
//                 break;
//             }
//             i--;
//         }
//         y = i;
//         i = 1;
//         while((max * i) % min != 0)
//         {
//             i++;
//         }
//         b = max * i;
//         int sum = b + y;
//         printf("%d,%d,%d\n",b,y,sum);
//     }
//     return 0;
// }

// //辗转相除法(欧几里得)
// int main()
// {
//     long n = 0;
//     long m = 0;
//     while(scanf("%ld %ld",&n,&m) == 2)
//     {
//         long i = n;
//         long j = m;
//         long r = 0;
//         while(r = i % j)//不需要判断二者大小，若前小于后会自动互换位置
//         {
//             i = j;
//             j = r;
//         }
//         printf("%ld\n",m*n/j + j);//m*n可能会溢出，可用long变量
//     }
//     return 0;
// }





//BC69 空心正方形图案
//输入n代表输出图形行数与正方形边*的个数
// int main()
// {
//     int n = 0;
//     scanf("%d",&n);
//     int i = 0;
//     int j = 0;
//     for(i = 0; i < n;i++)
//     {
//         if(i == 0 ||i == n-1 )
//         {
//             for(j = 0;j < n;j++)
//             {
//                 printf("* ");
//             }
//         }
//         else
//         {
//             for(j = 0;j < n;j++)
//             {
//                 if(j == 0||j == n-1)
//                 {
//                     printf("* ");
//                 }
//                 else
//                 {
//                     printf("  ");
//                 }
//             }
//         }
//         printf("\n");
//     }
//     return 0;
// }

// //鹏哥写法
// int main()
// {
//     int n = 0;
//     scanf("%d",&n);
//     int i = 0;
//     int j = 0;
//     for(i = 0; i < n;i++)
//     {
//         for(j = 0;j < n;j++)//统一判断
//         {
//             if(i == 0 || i == n-1 || j == 0 || j == n-1)
//                 printf("* ");
//             else
//                 printf("  ");
//         }
//         printf("\n");
//     }
//     return 0;
// }


//柔性数组
struct S
{
    int n;
    int arr[];
};
int main()
{
    // int sz = sizeof(struct S);
    // printf("%d\n",sz);//4
    struct S* ps = (struct S*)malloc(sizeof(struct S)+40);
    if(ps == NULL)
    {
        return 1;
    }
    ps->n = 10;
    int i = 0;
    for(i = 0;i < 10;i++)
    {
        ps->arr[i] = i;
    }
    for(i = 0;i < 10;i++)
    {
        printf("%d ",ps->arr[i]);
    }
    struct S* ptr = realloc(ps,sizeof(struct S)+80);
    if(ptr != NULL)
    {
        ps = ptr;
    }
    free(ps);
    ps = NULL;
    return 0;
}
